class Teilchen
{
  // INSTANZVARIABLEN
  float q; // Teilchenladung
  float m;
  int nachbarnNeutronen;
  int nachbarnProtonen;
  PVector x = new PVector(), v = new PVector(), F = new PVector(); // Position, Geschwindigkeit und Beschleunigung

  // KONSTRUKTOR
  Teilchen(PVector xTemp, PVector vTemp, float qTemp, float mTemp)
  {
    x = xTemp;
    v = vTemp;
    q = qTemp;
    m = mTemp;
  }

  // METHODEN
  // Wechselwirkung mit einem anderen Teilchen berechnen
  void wechselwirkung(Teilchen wechselwirkungspartner)
  {
    if (m < 1 || wechselwirkungspartner.m < 1) // Positronen sollen keine Wechselwirkung mit anderen Teilchen eingehen
      return;

    float abstand = PVector.sub(wechselwirkungspartner.x, x).mag() + 1; // Betrag der vektoriellen Differenz
    PVector richtung = PVector.sub(wechselwirkungspartner.x, x).normalize(); // Einheitsvektor zur Bestimmung der Richtung

    if (abstand < 60 && wechselwirkungspartner.m >= 1) // Falls ein Neutron bzw. Proton im Abstand von 60 Pixeln oder kleiner ist, so wird dieses als Nachbar gewertet
    {
      if (wechselwirkungspartner.q == 0)
        nachbarnNeutronen += 1;
      else if (wechselwirkungspartner.q > 0)
        nachbarnProtonen += 1;
    }

    // Änderung des Beschleunigungsvektors a durch die abstoßende Coulomb-Kraft
    F.add(PVector.mult(richtung, -0.1 * wechselwirkungspartner.q * q / pow(abstand, 2))); // Fc = n * q1 * q2 / r^2
    // Änderung des Beschleunigungsvektors a durch den anziehenden Teil der starken Kraft (vereinfacht, ohne e-Funktion)

    F.add(PVector.mult(richtung, 100.0 / pow(abstand, 4))); // F = n * / r^4
    // Änderung des Beschleunigungsvektors a durch den abstoßenden Teil der starken Kraft (vereinfacht, ohne e-Funktion)
    F.add(PVector.mult(richtung, -40000.0 / pow(abstand, 6))); // F = n * / r^6
    // Die Konstanten -0.1, 100.0 und -40000.0 wurden experimentell, also durch ausprobieren ermittelt
  }

  // Das Teilchen entsprechend der wirkenden Kräfte bewegen
  void bewegen(float dt)
  {
    F.add(PVector.mult(v, -0.001 * m)); /* Leichtes "Abkühlen" der Simulation, indem eine schwache, der Bewegungsrichtung der Teilchen 
     entgegengesetzte Beschleunigung wirkt. Der Faktor -0.001 hat die Maßeinheit s^-1 */

    v.add(PVector.mult(PVector.div(F, m), dt)); // v1 = v0 + a0 * dt
    x.add(PVector.mult(v, dt)); // x1 = x0 + v1 * dt
    F.set(0, 0, 0); // Beschleunigung auf null zurücksetzen

    if (q > 0 && nachbarnProtonen > nachbarnNeutronen && nachbarnProtonen > 0 && random(0.0, 1.0) <= 0.0025) // Falls ein Proton mehr Protonen als Neutronen in seiner Umgebung hat (= Protonenüberschuss), dann soll es zufällig zerfallen
    {
      teilchenListe.add(new Teilchen(new PVector(x.x, x.y), new PVector(random(-1, 1), random(-1, 1)), 1, 1.0/18.3615)); // Schnelles Positron aussenden
      q = 0; // Proton in Neutron umwandeln
    }

    nachbarnProtonen = 0;
    nachbarnNeutronen = 0;
  }

  // Protonen und Neutronen zeichnen
  void zeichnen()
  {
    noStroke();
    // Protonen (Teilchenladung q = 1) werden rot gezeichnet, Neutronen (Teilchenladung q = 0) weiß, Positronen (Teilchenladung q = 1) rot
    if (m >= 1 && q > 0)
    {
      fill(255, 0, 0);
      ellipse(x.x, x.y, 20, 20);
    } else if (m >= 1 && q == 0)
    {
      fill(255, 255, 255);
      ellipse(x.x, x.y, 20, 20);
    } else if (m < 1 && q > 0)
    {
      fill(255, 0, 0);
      ellipse(x.x, x.y, 10, 10);
    }
  }
}